﻿Friend Class Handler_ScheduleWatcher
    Private Shared mBackupTimeWatchDaemon As Threading.Thread

    Public Shared Sub Start()
        SetupEvents(True)
        mBackupTimeWatchDaemon = New Threading.Thread(AddressOf BackupTimeWatchDaemon)
        mBackupTimeWatchDaemon.IsBackground = True
        mBackupTimeWatchDaemon.Name = "Backup Schedule Watcher Daemon Thread"
        mBackupTimeWatchDaemon.Priority = Threading.ThreadPriority.Lowest
        mBackupTimeWatchDaemon.Start()

    End Sub
    Public Shared Sub [Stop]()
        If mBackupTimeWatchDaemon IsNot Nothing Then
            mBackupTimeWatchDaemon.Abort()
            mBackupTimeWatchDaemon.Join(10000)
            mBackupTimeWatchDaemon = Nothing
        End If
        SetupEvents(False)
    End Sub


    'this thread queues jobs for processing whenever it's scheduled time is up
    Private Shared Sub BackupTimeWatchDaemon()
        Try
            Do
                'try to find a job that is due for processing
                'this applies to all jobs with a ...
                Dim dtNow As Date = Now.ToUniversalTime
                For Each clsJob As Entities.Backup.Job In EntityHandlers.Backup.Jobs.GetAll
                    If clsJob.Status = Entities.Backup.JobStatus.Idle _
                        AndAlso clsJob.NextRunUtc <> Date.MinValue _
                        AndAlso clsJob.NextRunUtc < dtNow Then
                        'if more than one minute passed, we missed it
                        Dim tsOverDueBy As TimeSpan = dtNow.Subtract(clsJob.NextRunUtc)
                        If tsOverDueBy.Seconds < 60 Then
                            Handler_AnalyzeAndFindChanges.QueueJobIfNotPresentInQueue(clsJob)
                            clsJob.NextRunUtc = EntityHandlers.Backup.Jobs.CalculateNextRunTime(clsJob.Schedule)
                            EntityHandlers.Backup.Jobs.Save(clsJob)
                            Manager.OnJobInformation(clsJob, "Job scheduled to run and queued for processsing")
                            'ok, we missed our time slot. Do we run anyway?
                        ElseIf clsJob.Schedule IsNot Nothing AndAlso clsJob.Schedule.RunIfMissed Then
                            Handler_AnalyzeAndFindChanges.QueueJobIfNotPresentInQueue(clsJob)
                            clsJob.NextRunUtc = EntityHandlers.Backup.Jobs.CalculateNextRunTime(clsJob.Schedule)
                            EntityHandlers.Backup.Jobs.Save(clsJob)
                            Manager.OnJobInformation(clsJob, "Job schedule was missed but flagged to run anyway. Job was queued for processsing")
                        End If
                    End If
                Next
                If Diagnostics.Debugger.IsAttached Then
                    Threading.Thread.Sleep(5 * 1000)
                Else
                    Threading.Thread.Sleep(59 * 1000)
                End If
            Loop
        Catch ex As System.Threading.ThreadAbortException
            Return
        Catch ex As Exception
            Framework.Misc.HandleException(ex)
        End Try
    End Sub

    Private Shared Sub SetupEvents(ByVal startListening As Boolean)
        If startListening Then
            AddHandler Framework.Net.Manager.NodeStatusChanged, AddressOf EventHandler_NodeStatusChanged
            AddHandler EntityHandlers.Backup.IssuedContracts.Updated, AddressOf EventHandler_BackupIssuedContractsUpdated
        Else
            RemoveHandler Framework.Net.Manager.NodeStatusChanged, AddressOf EventHandler_NodeStatusChanged
            RemoveHandler EntityHandlers.Backup.IssuedContracts.Updated, AddressOf EventHandler_BackupIssuedContractsUpdated
        End If
    End Sub

    Private Shared Sub EventHandler_NodeStatusChanged(ByVal node As Framework.Net.Node)
        Try
            If node.IsOnline And Not node.IsDisconnecting Then
                For Each clsContract As Entities.Backup.IssuedContract In EntityHandlers.Backup.IssuedContracts.GetAllByBuddyId(node.BuddyId)
                    Commands.ContractUpdate.SendNotification(node, clsContract)
                Next
            End If
        Catch ex As Exception
            Framework.Misc.HandleException(ex)
        End Try
    End Sub
    Private Shared Sub EventHandler_BackupIssuedContractsUpdated(ByVal contract As Entities.Backup.IssuedContract)
        Try
            Dim clsNode As Framework.Net.Node
            clsNode = Framework.Net.Manager.GetOnlineByBuddyId(contract.IssuedToBuddyId)
            If clsNode IsNot Nothing Then
                Commands.ContractUpdate.SendNotification(clsNode, contract)
            End If
        Catch ex As Exception
            Framework.Misc.HandleException(ex)
        End Try
    End Sub

End Class
